package com.anji.topology;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import com.anji.topology.Topology.Hidden;


/**
 * 
 * @author slusk
 *
 */
public class XmlUtil {
	/**
	 * TESTING ONLY
	 * @param args
	 * @throws JAXBException
	 * @throws FileNotFoundException
	 */
	public static void main(String[] args) throws JAXBException, FileNotFoundException {
		/*
		TopologyDescriptor td = getTopologyDescriptor(TopologyDescriptor.class, new FileInputStream("properties/test.xml"));
		System.out.println(td);
		*/
	}
	
	/**
	 * Retrieves a topology descriptor from an Xml with the given file name.
	 * @param resource The name of the Xml file.
	 * @return The topology descriptor.
	 * @throws JAXBException
	 */
	public static Topology getTopologyDescriptor(String resource) throws JAXBException {
		InputStream inputStream = ClassLoader.getSystemResourceAsStream( resource );
	    String packageName = Topology.class.getPackage().getName();
	    JAXBContext jc = JAXBContext.newInstance( packageName );
	    Unmarshaller u = jc.createUnmarshaller();
//	    JAXBElement<Topology> doc = (JAXBElement<Topology>) u.unmarshal( inputStream );
//	    return doc.getValue();
	    Topology top = (Topology) u.unmarshal(inputStream);
	    return top;
	}
	
	/**
	 * Converts a BigInteger list (from the xml) into a standard int array.
	 * @param list The list of BigIntegers.
	 * @return The int array.
	 */
	public static int[] convertByteListToArray(List<Byte> list) {
		int[] a = new int[list.size()];
		int idx = 0;
		for (Byte i : list) {
			a[idx++] = i.intValue();
		}
		
		return a;
	}
	
	/**
	 * Converts a BigInteger list (from the xml) into a standard int array with a minimum number of dimensions; if 
	 * the list is shorter than the minimum, additional dimensions are added with a size of 1.
	 * @param list The list of BigIntegers.
	 * @param dimCastSize The minimum number of dimensions.
	 * @return The int array.
	 */
	public static int[] convertByteListToArray(List<Byte> list, int dimCastSize) {
		int[] a;

		a = (list.size() > dimCastSize) ? new int[list.size()] : new int[dimCastSize];
		
		for (int i = 0; i < Math.max(dimCastSize, list.size()); i++) {
			a[i] = i >= list.size() ? 1 : list.get(i).intValue();
		}
		
		return a;
	}
	
	/**
	 * Converts a list of layers into a two dimensional array of dimensions.
	 * @param allLayers The list of layers
	 * @param dimCastSize The size to cast the arrays to
	 * @return
	 */
	public static int[][] convertLayersListToArray(List<Layer> allLayers, int dimCastSize) {
		int[][] array = new int[allLayers.size()][];
		int idx = 0;
		for (Layer layer : allLayers) {
			array[idx++] = convertByteListToArray(layer.getDimensions(), dimCastSize);
		}
		return array;
	}
	
	/**
	 * Converts a topology descriptor into a list of Layers.
	 * @param td The topology descriptor.
	 * @return
	 */
	public static List<Layer> getAllLayers(Topology td) {
		List<Layer> list = new ArrayList<Layer>(); 
		
		list.add(new Layer(td.getInputs().getDimensions()));
		for (Hidden h : td.getHidden()) 
			list.add(new Layer(h.getDimensions()));
		list.add(new Layer(td.getOutputs().getDimensions()));
		
		return list;
	}
}
